home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1999 January: Mac OS SDK / Dev.CD Jan 99 SDK2.toast / Development Kits / TEC 1.4 / SampleCode / DropEncoder / Source / Shell.c < prev   
Encoding:
C/C++ Source or Header  |  1998-09-25  |  8.2 KB  |  312 lines  |  [TEXT/CWIE]

  1. /*************************************************************************************
  2. #
  3. #    Shell.c
  4. #    
  5. #   This is a simple application shell that we use to handle the standard mac stuff.
  6. #   In general, the routines in this code should be as generic as possible, and any
  7. #   custom code should be included in CustomApp.c instead.
  8. #
  9. #    Author: Timothy Carroll
  10. #    Apple Developer Technical Support
  11. #    timc@apple.com
  12. #
  13. #    Revision: Jason Yeo
  14. #
  15. #    Modification History: 
  16. #
  17. #    2/9/97        TMC     Initial Release
  18. #
  19. #    9/12/97        JY         Updated for:
  20. #                        TEC 1.2.1 
  21. #                        Universal Interfaces 3.0
  22. #                        CodeWarrior 11 projects
  23. #
  24. #    Copyright © 1997 Apple Computer, Inc., All Rights Reserved
  25. #
  26. #
  27. #    You may incorporate this sample code into your applications without
  28. #    restriction, though the sample code has been provided "AS IS" and the
  29. #    responsibility for its operation is 100% yours.  However, what you are
  30. #    not permitted to do is to redistribute the source as "DSC Sample Code"
  31. #    after having made changes. If you're going to re-distribute the source,
  32. #    we require that you make it clear in the source that the code was
  33. #    descended from Apple Sample Code, but that you've made changes.
  34. #
  35. *************************************************************************************/
  36.  
  37. #include "CustomApp.h"
  38.  
  39.  
  40.  
  41. /*********************************************************************************
  42. #    SHELL GLOBALS
  43. #    
  44. *********************************************************************************/
  45. Boolean         gQuittingApp;
  46. Boolean         gAppForeGround;
  47. TPreferences    gPreferences;
  48.  
  49. // UPPs for our standard apple events
  50. static AEEventHandlerUPP gOpenApp = NULL;
  51. static AEEventHandlerUPP gOpenDoc = NULL;
  52. static AEEventHandlerUPP gPrintDoc = NULL;
  53. static AEEventHandlerUPP gQuitApp = NULL;
  54.  
  55.  
  56.  
  57.  
  58. void         main (void);
  59. OSStatus     InitStandardAEHandlers (void);
  60. OSStatus    TerminateAppStandardAEHandlers (void);
  61. OSStatus    InitAppPreferences (void);
  62.  
  63.  
  64. void main (void)
  65. {
  66.     int loop;
  67.     OSStatus theErr = noErr;
  68.     
  69.     EventRecord        theEvent;
  70.     UInt32            nextTimeToCheckForEvents = 0;
  71.     
  72.     
  73.     // Expand the heap and set up a block of master pointers
  74.     MaxApplZone();
  75.     
  76.     for (loop = 0; loop < kNumberOfMasters; loop++)
  77.         MoreMasters();
  78.     
  79.     // Standard Mac Init
  80.     InitGraf(&qd.thePort);
  81.     InitFonts();
  82.     InitWindows();
  83.     InitMenus();
  84.     TEInit();
  85.     InitDialogs(nil);
  86.     InitCursor();
  87.  
  88.     // Initialize standard AppleEvent handlers
  89.     theErr = InitStandardAEHandlers();
  90.     FAIL_OSERR (theErr, "\pError: Failed to initialize event handlers.")
  91.     
  92.     // Initialize the App's custom preferences (from a prefs file perhaps)
  93.     theErr = InitAppPreferences();
  94.     FAIL_OSERR (theErr, "\pError: Failed to load app's preferences")
  95.     
  96.     // Perform custom initialization
  97.     theErr = InitApp();
  98.     FAIL_OSERR (theErr, "\pError: Custom App Initialization failed.")
  99.  
  100.     gQuittingApp = false;
  101.     gAppForeGround = true;
  102.  
  103.     // STANDARD EVENT LOOP
  104.     
  105.     do
  106.     {
  107.         // If the app wants a slice of time, we give it a bit of time to work on stuff.
  108.         // If the app is in the background, it gets one block of time, otherwise we'll
  109.         // keep giving it time until it no longer wants any or when the event interval
  110.         // is up.
  111.         
  112.         // We'll also bail from doing any work if TimeSlice returns an error.
  113.         
  114.         // How's this for a funky loop?! :)
  115.         
  116.         theErr = noErr;
  117.         
  118.         do {}
  119.         while (    AppWantsTime() &&
  120.                 ((theErr = TimeSlice()) != noErr) &&
  121.                 gAppForeGround &&
  122.                 (TickCount() < nextTimeToCheckForEvents));
  123.         
  124.         FAIL_OSERR (theErr, "\pError: TimeSlice returned an error.")
  125.         
  126.         nextTimeToCheckForEvents = TickCount() + kEventInterval;
  127.         
  128.         (void) WaitNextEvent(everyEvent,&theEvent,kSleepTime,NULL);
  129.         theErr = HandleEvent(&theEvent);
  130.         FAIL_OSERR (theErr, "\pError: Event was unable to be handled.")
  131.     
  132.     } while (!gQuittingApp);
  133.  
  134.     
  135.     error:
  136.     cleanup:
  137.     // The shell by default just quits out when an error occurs.  A real app should
  138.     // provide some sort of error message.
  139.     
  140.     theErr = TerminateAppStandardAEHandlers ();
  141.     
  142.     theErr = TerminateApp();
  143.     
  144.     return;
  145. }
  146.  
  147.  
  148.  
  149. OSStatus     InitStandardAEHandlers (void)
  150. {
  151.     OSStatus theErr = noErr;
  152.     
  153.     // build the UPPs for our standard event handlers
  154.     
  155.     gOpenApp  = NewAEEventHandlerProc (HandleOpenAppEvent);
  156.     gOpenDoc  = NewAEEventHandlerProc (HandleOpenDocEvent);
  157.     gPrintDoc = NewAEEventHandlerProc (HandlePrintDocEvent);
  158.     gQuitApp  = NewAEEventHandlerProc (HandleQuitAppEvent);
  159.  
  160.     // Install the event handlers into the Application's Apple Event table.
  161.  
  162.     theErr = AEInstallEventHandler(kCoreEventClass,kAEOpenApplication,gOpenApp,0,false);
  163.     FAIL_OSERR (theErr, "\pError: Failed to install a core event handler")
  164.     
  165.     theErr = AEInstallEventHandler(kCoreEventClass,kAEOpenDocuments,gOpenDoc,0,false);
  166.     FAIL_OSERR (theErr, "\pError: Failed to install a core event handler")
  167.     
  168.     theErr = AEInstallEventHandler(kCoreEventClass,kAEPrintDocuments,gPrintDoc,0,false);
  169.     FAIL_OSERR (theErr, "\pError: Failed to install a core event handler")
  170.     
  171.     theErr = AEInstallEventHandler(kCoreEventClass,kAEQuitApplication,gQuitApp,0,false);
  172.     FAIL_OSERR (theErr, "\pError: Failed to install a core event handler")
  173.  
  174.     // Everything went successfully, we can return without any errors.
  175.     goto cleanup;
  176.     
  177.     error:
  178.     if (theErr == noErr)
  179.         theErr = paramErr;
  180.         
  181.     cleanup:
  182.     return theErr;
  183.     
  184. }
  185.     
  186.  
  187.  
  188. OSStatus    TerminateAppStandardAEHandlers (void)
  189. {
  190.     // Remove the events from the dispatch tables, ignoring any errors
  191.     (void) AERemoveEventHandler(kCoreEventClass,kAEOpenApplication,gOpenApp,false);
  192.     (void) AERemoveEventHandler(kCoreEventClass,kAEOpenDocuments,gOpenDoc,false);
  193.     (void) AERemoveEventHandler(kCoreEventClass,kAEPrintDocuments,gPrintDoc,false);
  194.     (void) AERemoveEventHandler(kCoreEventClass,kAEQuitApplication,gQuitApp,false);
  195.     
  196.     // Dispose of the Routine Descriptors
  197.     if (gOpenApp)
  198.     {
  199.         DisposeRoutineDescriptor (gOpenApp);
  200.         gOpenApp = NULL;
  201.     }
  202.     
  203.     if (gOpenDoc)
  204.     {
  205.         DisposeRoutineDescriptor (gOpenDoc);
  206.         gOpenDoc = NULL;
  207.     }
  208.  
  209.     if (gPrintDoc)
  210.     {
  211.         DisposeRoutineDescriptor (gPrintDoc);
  212.         gPrintDoc = NULL;
  213.     }
  214.  
  215.     if (gQuitApp)
  216.     {
  217.         DisposeRoutineDescriptor (gQuitApp);
  218.         gQuitApp = NULL;
  219.     }
  220.     
  221.     return noErr;
  222. }
  223.  
  224.  
  225. // We use OSErr instead of OSStatus because this can be returned by an AppleEvent
  226. OSErr CheckAppleEventForMissingParams(AppleEvent *event)
  227. {
  228.     OSErr        theErr = noErr;
  229.     Size         actualSize;
  230.     DescType    returnedType;
  231.  
  232.     theErr = AEGetAttributePtr(event,keyMissedKeywordAttr,typeWildCard, &returnedType,nil,0,&actualSize);
  233.     
  234.     // If we found a missing parameter, we should ignore this event.
  235.     if (theErr == noErr)
  236.         theErr = errAEEventNotHandled;
  237.     // Otherwise, if we couldn't find a missing attribute, the event should be handled.
  238.     else if (theErr == errAEDescNotFound)
  239.         theErr = noErr;    
  240.     
  241.     return theErr;
  242. }
  243.  
  244. OSStatus DispatchQuitEvent (void)
  245. {
  246.     // create a quit event and dispatch it to ourself.
  247.  
  248.     OSStatus             theErr = noErr;
  249.     AppleEvent            quitEvent, quitReply;
  250.     ProcessSerialNumber process;
  251.     AEAddressDesc        address;
  252.     
  253.     quitEvent.dataHandle = NULL;
  254.     address.dataHandle   = NULL;
  255.     
  256.     // Create a descriptor for us
  257.     process.highLongOfPSN = 0;
  258.     process.lowLongOfPSN = kCurrentProcess;
  259.     
  260.     theErr = AECreateDesc (typeProcessSerialNumber, (Ptr)&process, sizeof (process), &address);
  261.     FAIL_OSERR (theErr, "\pError: Failed to create a process descriptor")
  262.     
  263.     // Create the quit event
  264.     theErr = AECreateAppleEvent(kCoreEventClass, kAEQuitApplication, &address,
  265.                                         kAutoGenerateReturnID, kAnyTransactionID, &quitEvent);
  266.     FAIL_OSERR (theErr, "\pError: Failed to generate the quit AppleEvent")
  267.  
  268.     // Dispatch the event
  269.     theErr = AESend (&quitEvent, &quitReply, kAENoReply+kAEAlwaysInteract,
  270.                                     kAENormalPriority, kAEDefaultTimeout, nil, nil);
  271.     goto cleanup;
  272.     
  273. error:
  274.     if (theErr == noErr)
  275.         theErr = paramErr;
  276.         
  277. cleanup:
  278.  
  279.     if (quitEvent.dataHandle)
  280.         (void) AEDisposeDesc (&quitEvent);
  281.     if (address.dataHandle)
  282.         (void) AEDisposeDesc (&address);
  283.         
  284.     return theErr;
  285. }
  286.  
  287. OSStatus InitAppPreferences (void)
  288. {
  289.     OSStatus theErr = noErr;
  290.     
  291.     theErr = ReadPreferencesFile(&gPreferences);
  292.     if (theErr == noErr)
  293.         goto cleanup;
  294.     
  295.     // We either have a corrupted prefs or it didn't exist.  Restore to default
  296.     // prefs and save out a new file.
  297.     
  298.     theErr = SetDefaultPreferences(&gPreferences);
  299.     FAIL_OSERR (theErr, "\pError: Failed to set default prefs for the app");
  300.     
  301.     theErr = WritePreferencesFile (&gPreferences);
  302.     FAIL_OSERR (theErr, "\pError: Unable to write a prefs file");
  303.     
  304.     goto cleanup;
  305.     
  306. error:
  307.     if (theErr == noErr)
  308.         theErr = paramErr;
  309.     
  310. cleanup:
  311.     return theErr;
  312. }